library(tidyverse)  # For data manipulation and visualization
library(readr)      # For reading CSV data
library(lubridate)  # For date manipulation
library(caret)      # For creating training and test sets, and modeling
library(plotly)
library(ggplot2)
library(readr)
library(RColorBrewer)
library(readxl)
library(scales)
library(hexbin)
library(viridis)
Warning: package ‘viridis’ was built under R version 4.2.3Loading required package: viridisLite
Warning: package ‘viridisLite’ was built under R version 4.2.3
Attaching package: ‘viridis’

The following object is masked from ‘package:scales’:

    viridis_pal

party_dictionary <- data.frame(
  Original = c("ACE","AKI","AIC","AIP","AMP","APF","AE","CIT","CMD","CMP","COM","CNC","CRV","CON","CST","COU","DCG","DNL","DEM","D/C","DFL","DGR","FED","FLP","FRE","GWP","GRT","GRE","GR","HRP","IDP","IND","IAP","ICD","IGR","IP","IDE","IGD","JCN","JUS","LRU","LBR","LFT","LBL","LIB","LBU","MTP","NDP","NLP","NA","NJC","NPP","NPA","NOP","NNE","N","NON","OE","OTH","PG","PSL","PAF","PFP","PFD","POP","PPY","PCH","PPD","PRO","NAP","PRI","RUP","REF","REP","RES","RTL","SEP","SLP","SUS","SOC","SWP","TX","TWR","TEA","THD","LAB","USP","UST","UN","UC","UNI","UNK","VET","WTP","W"),
  Label = c("Ace Party","Alaskan Independence Party","American Independent Conservative","American Independent Party","American Party","American People's Freedom Party","Americans Elect","Citizens' Party","Commandments Party","Commonwealth Party of the U.S.","Communist Party","Concerned Citizens Party Of Connecticut","Conservative Party","Constitution Party","Constitutional","Country","D.C. Statehood Green Party","Democratic -Nonpartisan League","Democratic Party","Democratic/Conservative","Democratic-Farmer-Labor","Desert Green Party","Federalist","Freedom Labor Party","Freedom Party","George Wallace Party","Grassroots","Green Party","Green-Rainbow","Human Rights Party","Independence Party","Independent","Independent American Party","Independent Conservative Democratic","Independent Green","Independent Party","Independent Party of Delaware","Industrial Government Party","Jewish/Christian National","Justice Party","La Raza Unida","Labor Party","Less Federal Taxes","Liberal Party","Libertarian Party","Liberty Union Party","Mountain Party","National Democratic Party","Natural Law Party","New Alliance","New Jersey Conservative Party","New Progressive Party","No Party Affiliation","No Party Preference","None","Nonpartisan","Non-Party","One Earth Party","Other","Pacific Green","Party for Socialism and Liberation","Peace And Freedom","Peace And Freedom Party","Peace Freedom Party","People Over Politics","People's Party","Personal Choice Party","Popular Democratic Party","Progressive Party","Prohibition Party","Puerto Rican Independence Party","Raza Unida Party","Reform Party","Republican Party","Resource Party","Right To Life","Socialist Equality Party","Socialist Labor Party","Socialist Party","Socialist Party U.S.A.","Socialist Workers Party","Taxpayers","Taxpayers Without Representation","Tea Party","Theo-Democratic","U.S. Labor Party","U.S. People's Party","U.S. Taxpayers Party","Unaffiliated","United Citizen","United Party","Unknown","Veterans Party","We the People","Write-In")
)
cand_data <-  read.csv2(file = "C:/Users/18137/Downloads/candidate_summary_2020.csv", sep = "," , )
cand_data$Total_Contribution <- as.numeric(cand_data$Total_Contribution)
cand_data$Total_Receipt <- as.numeric(cand_data$Total_Receipt)

cand_data <- cand_data %>%
  left_join(party_dictionary, by = c("Cand_Party_Affiliation" = "Original")) %>%
  # Optionally, you might want to remove the original column and rename the new one
  select(-Cand_Party_Affiliation) %>%
  rename(Cand_Party_Affiliation = Label)

election_results <- read_excel("C:/Users/18137/Downloads/federalelections2020.xlsx")
New names:
senate_results <- read_excel("C:/Users/18137/Downloads/federalelections2020.xlsx", sheet = "12. US Senate Results by State")
house_results <- read_excel("C:/Users/18137/Downloads/federalelections2020.xlsx", sheet = "13. US House Results by State")
pres_primary_results <- read_excel("C:/Users/18137/Downloads/federalelections2020.xlsx", sheet = "9. 2020 Pres General Results")
senate_results <- senate_results %>%
  mutate(Win_Lose = as.numeric('GE Winner Indicator' == "W"))

house_results <- house_results %>%
  mutate(Win_Lose = as.numeric('GE Winner Indicator' == "W"))

pres_primary_results <- pres_primary_results %>%
  mutate(Win_Lose = as.numeric('Winner_Indicator' == "W"))
cand_data <- cand_data %>% group_by(Cand_Party_Affiliation) %>% filter(Total_Receipt > 0)


all_election_results <- bind_rows(senate_results, house_results, pres_primary_results)

final_data <- cand_data %>%
  left_join(all_election_results, by = c("Cand_Id" = "FEC ID"))


final_data$Win_Lose[is.na(final_data$Win_Lose)] <- 0
head(final_data)

merged_data <- final_data %>%
  mutate(Total_Contribution = if_else(is.na(Total_Contribution), median(Total_Contribution, na.rm = TRUE), Total_Contribution))

summary(merged_data)
  Link_Image         Cand_Name           Cand_Id          Cand_Office        Cand_Office_St    
 Length:2938        Length:2938        Length:2938        Length:2938        Length:2938       
 Class :character   Class :character   Class :character   Class :character   Class :character  
 Mode  :character   Mode  :character   Mode  :character   Mode  :character   Mode  :character  
                                                                                               
                                                                                               
                                                                                               
                                                                                               
 Cand_Office_Dist Cand_Incumbent_Challenger_Open_Seat Total_Receipt       Total_Disbursement
 Min.   : 0.000   Length:2938                         Min.   :1.000e+00   Length:2938       
 1st Qu.: 0.000   Class :character                    1st Qu.:2.124e+04   Class :character  
 Median : 4.000   Mode  :character                    Median :1.587e+05   Mode  :character  
 Mean   : 7.642                                       Mean   :3.534e+07                     
 3rd Qu.:10.750                                       3rd Qu.:1.560e+06                     
 Max.   :53.000                                       Max.   :1.125e+09                     
                                                                                            
 Cash_On_Hand_COP   Debt_Owed_By_Committee Coverage_End_Date  Cand_Street_1      Cand_Street_2     
 Length:2938        Length:2938            Length:2938        Length:2938        Length:2938       
 Class :character   Class :character       Class :character   Class :character   Class :character  
 Mode  :character   Mode  :character       Mode  :character   Mode  :character   Mode  :character  
                                                                                                   
                                                                                                   
                                                                                                   
                                                                                                   
  Cand_City          Cand_State           Cand_Zip         Individual_Itemized_Contribution
 Length:2938        Length:2938        Min.   :        0   Length:2938                     
 Class :character   Class :character   1st Qu.:    22314   Class :character                
 Mode  :character   Mode  :character   Median :    48216   Mode  :character                
                                       Mean   : 26963948                                   
                                       3rd Qu.:    82414                                   
                                       Max.   :995100298                                   
                                       NA's   :144                                         
 Individual_Unitemized_Contribution Individual_Contribution Other_Committee_Contribution
 Length:2938                        Length:2938             Length:2938                 
 Class :character                   Class :character        Class :character            
 Mode  :character                   Mode  :character        Mode  :character            
                                                                                        
                                                                                        
                                                                                        
                                                                                        
 Party_Committee_Contribution Cand_Contribution  Total_Contribution 
 Length:2938                  Length:2938        Min.   :0.000e+00  
 Class :character             Class :character   1st Qu.:1.254e+04  
 Mode  :character             Mode  :character   Median :9.946e+04  
                                                 Mean   :2.524e+07  
                                                 3rd Qu.:1.226e+06  
                                                 Max.   :1.090e+09  
                                                                    
 Transfer_From_Other_Auth_Committee  Cand_Loan          Other_Loan         Total_Loan       
 Length:2938                        Length:2938        Length:2938        Length:2938       
 Class :character                   Class :character   Class :character   Class :character  
 Mode  :character                   Mode  :character   Mode  :character   Mode  :character  
                                                                                            
                                                                                            
                                                                                            
                                                                                            
 Offsets_To_Operating_Expenditure Offsets_To_Fundraising Offsets_To_Leagal_Accounting
 Length:2938                      Length:2938            Length:2938                 
 Class :character                 Class :character       Class :character            
 Mode  :character                 Mode  :character       Mode  :character            
                                                                                     
                                                                                     
                                                                                     
                                                                                     
 Other_Receipts     Operating_Expenditure Exempt_Legal_Accounting_Disbursement
 Length:2938        Length:2938           Length:2938                         
 Class :character   Class :character      Class :character                    
 Mode  :character   Mode  :character      Mode  :character                    
                                                                              
                                                                              
                                                                              
                                                                              
 Fundraising_Disbursement Transfer_To_Other_Auth_Committee Cand_Loan_Repayment Other_Loan_Repayment
 Length:2938              Length:2938                      Length:2938         Length:2938         
 Class :character         Class :character                 Class :character    Class :character    
 Mode  :character         Mode  :character                 Mode  :character    Mode  :character    
                                                                                                   
                                                                                                   
                                                                                                   
                                                                                                   
 Total_Loan_Repayment Individual_Refund  Party_Committee_Refund Other_Committee_Refund
 Length:2938          Length:2938        Length:2938            Length:2938           
 Class :character     Class :character   Class :character       Class :character      
 Mode  :character     Mode  :character   Mode  :character       Mode  :character      
                                                                                      
                                                                                      
                                                                                      
                                                                                      
 Total_Contribution_Refund Other_Disbursements Net_Contribution   Net_Operating_Expenditure
 Length:2938               Length:2938         Length:2938        Length:2938              
 Class :character          Class :character    Class :character   Class :character         
 Mode  :character          Mode  :character    Mode  :character   Mode  :character         
                                                                                           
                                                                                           
                                                                                           
                                                                                           
 Cash_On_Hand_BOP   Debt_Owe_To_Committee Coverage_Start_Date Cand_Party_Affiliation       1         
 Length:2938        Length:2938           Length:2938         Length:2938            Min.   :   3.0  
 Class :character   Class :character      Class :character    Class :character       1st Qu.: 390.8  
 Mode  :character   Mode  :character      Mode  :character    Mode  :character       Median :1102.0  
                                                                                     Mean   :1511.8  
                                                                                     3rd Qu.:2579.2  
                                                                                     Max.   :4036.0  
                                                                                     NA's   :574     
 STATE ABBREVIATION    STATE             DISTRICT         (I) Incumbent Indicator
 Length:2938        Length:2938        Length:2938        Length:2938            
 Class :character   Class :character   Class :character   Class :character       
 Mode  :character   Mode  :character   Mode  :character   Mode  :character       
                                                                                 
                                                                                 
                                                                                 
                                                                                 
 CANDIDATE NAME (First) CANDIDATE NAME (Last) CANDIDATE NAME     TOTAL VOTES           PARTY          
 Length:2938            Length:2938           Length:2938        Length:2938        Length:2938       
 Class :character       Class :character      Class :character   Class :character   Class :character  
 Mode  :character       Mode  :character      Mode  :character   Mode  :character   Mode  :character  
                                                                                                      
                                                                                                      
                                                                                                      
                                                                                                      
 PRIMARY VOTES        PRIMARY %       RUNOFF VOTES       RUNOFF %      GENERAL VOTES     
 Length:2938        Min.   :0.0001   Min.   :  1570   Min.   :0.2405   Length:2938       
 Class :character   1st Qu.:0.1105   1st Qu.:  8528   1st Qu.:0.4304   Class :character  
 Mode  :character   Median :0.3107   Median : 16102   Median :0.5116   Mode  :character  
                    Mean   :0.4042   Mean   : 48039   Mean   :0.5072                     
                    3rd Qu.:0.6751   3rd Qu.: 33884   3rd Qu.:0.5937                     
                    Max.   :1.0000   Max.   :502516   Max.   :0.7595                     
                    NA's   :1344     NA's   :2888     NA's   :2888                       
   GENERAL %      GE RUNOFF ELECTION VOTES (GA, LA) GE RUNOFF ELECTION % (GA, LA)
 Min.   :0.0000   Min.   :2195841                   Min.   :0.4896               
 1st Qu.:0.0135   1st Qu.:2210195                   1st Qu.:0.4928               
 Median :0.3874   Median :2242451                   Median :0.5000               
 Mean   :0.3436   Mean   :2242464                   Mean   :0.5000               
 3rd Qu.:0.5628   3rd Qu.:2274721                   3rd Qu.:0.5072               
 Max.   :1.0000   Max.   :2289113                   Max.   :0.5104               
 NA's   :1472     NA's   :2934                      NA's   :2934                 
 COMBINED GE PARTY TOTALS (when applicable) COMBINED % (when applicable) PE WINNER INDICATOR
 Mode:logical                               Mode:logical                 Length:2938        
 NA's:2938                                  NA's:2938                    Class :character   
                                                                         Mode  :character   
                                                                                            
                                                                                            
                                                                                            
                                                                                            
 GE WINNER INDICATOR  FOOTNOTES            Win_Lose GE RUNOFF ELECTION VOTES (GA, GU, LA)
 Length:2938         Length:2938        Min.   :0   Min.   : 7090                        
 Class :character    Class :character   1st Qu.:0   1st Qu.: 9623                        
 Mode  :character    Mode  :character   Median :0   Median :20296                        
                                        Mean   :0   Mean   :24216                        
                                        3rd Qu.:0   3rd Qu.:34889                        
                                        Max.   :0   Max.   :49183                        
                                                    NA's   :2934                         
 GE RUNOFF ELECTION % (GA, GU, LA) COMBINED GE PARTY TOTALS (CT, NY) COMBINED % (CT, NY)
 Min.   :0.3798                    Min.   :  3164                    Min.   :0.0094     
 1st Qu.:0.3978                    1st Qu.:149449                    1st Qu.:0.4321     
 Median :0.5000                    Median :181021                    Median :0.5445     
 Mean   :0.5000                    Mean   :170471                    Mean   :0.5273     
 3rd Qu.:0.6022                    3rd Qu.:206310                    3rd Qu.:0.5929     
 Max.   :0.6202                    Max.   :234933                    Max.   :0.9079     
 NA's   :2934                      NA's   :2836                      NA's   :2836       
 GENERAL ELECTION DATE  FIRST NAME         LAST NAME         LAST NAME,  FIRST  GENERAL RESULTS   
 Min.   :2020-11-03    Length:2938        Length:2938        Length:2938        Min.   :       1  
 1st Qu.:2020-11-03    Class :character   Class :character   Class :character   1st Qu.:     181  
 Median :2020-11-03    Mode  :character   Mode  :character   Mode  :character   Median :    3404  
 Mean   :2020-11-03                                                             Mean   :  376663  
 3rd Qu.:2020-11-03                                                             3rd Qu.:   80633  
 Max.   :2020-11-03                                                             Max.   :11110639  
 NA's   :2516                                                                   NA's   :2518      
 TOTAL VOTES #  COMBINED GE PARTY TOTALS (NY) COMBINED % (NY)  WINNER INDICATOR   ELECTORAL VOTES   
 Min.   : NA    Length:2938                   Min.   :0.3774   Length:2938        Length:2938       
 1st Qu.: NA    Class :character              1st Qu.:0.3774   Class :character   Class :character  
 Median : NA    Mode  :character              Median :0.4930   Mode  :character   Mode  :character  
 Mean   :NaN                                  Mean   :0.4930                                        
 3rd Qu.: NA                                  3rd Qu.:0.6087                                        
 Max.   : NA                                  Max.   :0.6087                                        
 NA's   :2938                                 NA's   :2932                                          
# Ensure Win_Lose is a factor for logistic regression
merged_data$Win_Lose <- as.factor(merged_data$Win_Lose)

# Fit the model
model <- glm(Win_Lose ~ Total_Contribution, data = merged_data, family = binomial(),control = glm.control(maxit = 10000))
Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred
# Check the summary
summary(model)

Call:
glm(formula = Win_Lose ~ Total_Contribution, family = binomial(), 
    data = merged_data, control = glm.control(maxit = 10000))

Deviance Residuals: 
       Min          1Q      Median          3Q         Max  
-2.107e-08  -2.107e-08  -2.107e-08  -2.107e-08  -2.107e-08  

Coefficients:
                     Estimate Std. Error z value Pr(>|z|)
(Intercept)        -3.057e+01  4.951e+04  -0.001        1
Total_Contribution -1.963e-22  3.847e-04   0.000        1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 0.0000e+00  on 2937  degrees of freedom
Residual deviance: 1.3047e-12  on 2936  degrees of freedom
AIC: 4

Number of Fisher Scoring iterations: 29
set.seed(123)  # for reproducibility
training_samples <- createDataPartition(merged_data$Win_Lose, p = 0.8, list = FALSE)

train_data <- merged_data[training_samples, ]
test_data <- merged_data[-training_samples, ]

# Predict on test set
predictions <- predict(model, test_data, type = "response")
predicted_class <- if_else(predictions > 0.5, 1, 0)

# Adjusting the sampling method to ensure stratification
training_samples <- createDataPartition(merged_data$Win_Lose, p = 0.8, list = TRUE, times = 1)

train_data <- merged_data[training_samples[[1]], ]
test_data <- merged_data[-training_samples[[1]], ]

test_data$Win_Lose <- factor(test_data$Win_Lose, levels = c("0", "1"))

# Ensure predicted_class is a factor with both levels
predicted_class <- factor(predicted_class, levels = c("0", "1"))

confusionMatrix(predicted_class, test_data$Win_Lose)
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 587   0
         1   0   0
                                     
               Accuracy : 1          
                 95% CI : (0.9937, 1)
    No Information Rate : 1          
    P-Value [Acc > NIR] : 1          
                                     
                  Kappa : NaN        
                                     
 Mcnemar's Test P-Value : NA         
                                     
            Sensitivity :  1         
            Specificity : NA         
         Pos Pred Value : NA         
         Neg Pred Value : NA         
             Prevalence :  1         
         Detection Rate :  1         
   Detection Prevalence :  1         
      Balanced Accuracy : NA         
                                     
       'Positive' Class : 0          
                                     
# Calculate accuracy or other performance metrics
accuracy <- sum(predicted_class == test_data$Win_Lose) / nrow(test_data)
print(paste("Accuracy:", accuracy))
[1] "Accuracy: 1"
conTotal <- cand_data$Total_Contribution 

fig1 <- cand_data %>% 
  ggplot(aes(conTotal, Cand_State)) + geom_col(aes(fill = cand_data$Cand_State)) + scale_x_continuous(labels = scales::label_dollar(prefix = "$"))

ggplotly(fig1)
cand_by_affiliation_Total_Receipt <- cand_data %>% 
  group_by(Cand_Party_Affiliation) %>% 
  filter(Total_Receipt > 0) %>% 
  arrange(Total_Receipt)


cand_by_affiliation_Total_Receipt <- data.frame(cand_by_affiliation_Total_Receipt$Cand_Party_Affiliation, cand_by_affiliation_Total_Receipt$Total_Receipt)

arg_data <- aggregate(cand_by_affiliation_Total_Receipt$cand_by_affiliation_Total_Receipt.Total_Receipt,
  list(Category = cand_by_affiliation_Total_Receipt$cand_by_affiliation_Total_Receipt.Cand_Party_Affiliation),
  sum)

arg_data <- arg_data %>% top_n(2)

ggplot(arg_data, aes(x = Category, y = x)) +  geom_col(aes(fill = Category)) + scale_y_continuous(labels = scales::label_dollar(prefix = "$", suffix = ""))
# Assuming 'cand_data' is your data frame and it has been loaded into your R session
distinct_parties <- cand_data %>%
  select(Cand_Party_Affiliation) %>%  # Select the column of interest
  distinct() %>%                      # Get distinct/unique entries
  arrange(Cand_Party_Affiliation)     # Optional: arrange them alphabetically

# To view the distinct party affiliations
print(distinct_parties)
receipt_data <- cand_data %>%
    group_by(Cand_Party_Affiliation) %>%
    summarize(Total_Receipt = sum(Total_Receipt, na.rm = TRUE)) %>%
    filter(Total_Receipt > 0) %>%  
    ggplot(aes(x = Cand_Party_Affiliation, y = Total_Receipt, fill = Cand_Party_Affiliation)) +
    geom_bar(stat = "identity") +
    scale_fill_viridis(discrete = TRUE, option = "M") +
    scale_y_log10(labels = label_dollar(scale = 1)) +
    labs(x = "Party Affiliation",
         y = "Log of Total Receipts (Dollars)",
         title = "Total Receipts by Party Affiliation") +
    theme_minimal() +
    theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5))

plotly_receipt_data <- ggplotly(receipt_data)
plotly_receipt_data
Congressional_data <- cand_data %>% 
  group_by(Cand_Office) %>% 
  filter(Cand_Office != "P") %>% 
  arrange(Total_Contribution)

Congressional_data <- aggregate(Congressional_data$Total_Contribution,
  list(Category = Congressional_data$Cand_Office ),
  sum)

president_data <- cand_data %>% 
  group_by(Cand_Office) %>% 
  filter(Cand_Office == "P") %>% 
  arrange(Total_Contribution)
Congressional_data %>% ggplot(aes(x = x, y = Category)) + geom_col(aes(fill = Category)) + scale_x_continuous(label = scales::label_dollar(prefix = "$"))
fig1 <- cand_data %>%
    group_by(Cand_State) %>%
    summarise(Total_Contribution = sum(Total_Contribution)) %>%
    filter(Total_Contribution > 0) %>%  # Filtering out zeros
    ggplot(aes(x = Cand_State, y = Total_Contribution, fill = Cand_State)) +
    geom_bar(stat = "identity") +
    scale_fill_viridis(discrete = TRUE, option = "D") +  # Using viridis for discrete color mapping
    scale_y_log10(labels = scales::label_dollar(scale = 1)) +  # Formatting y-axis as dollar values
    theme_minimal() +
    labs(title = "Total Contributions by State",
         y = "Log of Total Contributions (Dollars)",
         x = "State") +
    theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5))  # Vertical x-axis labels

# Convert to Plotly interactive plot
plotly_fig1 <- ggplotly(fig1)
plotly_fig1
LS0tDQp0aXRsZTogIkZFQyBBbmFseXNpcyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCg0KDQpgYGB7cn0NCg0KbGlicmFyeSh0aWR5dmVyc2UpICAjIEZvciBkYXRhIG1hbmlwdWxhdGlvbiBhbmQgdmlzdWFsaXphdGlvbg0KbGlicmFyeShyZWFkcikgICAgICAjIEZvciByZWFkaW5nIENTViBkYXRhDQpsaWJyYXJ5KGx1YnJpZGF0ZSkgICMgRm9yIGRhdGUgbWFuaXB1bGF0aW9uDQpsaWJyYXJ5KGNhcmV0KSAgICAgICMgRm9yIGNyZWF0aW5nIHRyYWluaW5nIGFuZCB0ZXN0IHNldHMsIGFuZCBtb2RlbGluZw0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShSQ29sb3JCcmV3ZXIpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkoc2NhbGVzKQ0KbGlicmFyeShoZXhiaW4pDQpsaWJyYXJ5KHZpcmlkaXMpDQoNCg0KYGBgDQoNCmBgYHtyfQ0KDQpwYXJ0eV9kaWN0aW9uYXJ5IDwtIGRhdGEuZnJhbWUoDQogIE9yaWdpbmFsID0gYygiQUNFIiwiQUtJIiwiQUlDIiwiQUlQIiwiQU1QIiwiQVBGIiwiQUUiLCJDSVQiLCJDTUQiLCJDTVAiLCJDT00iLCJDTkMiLCJDUlYiLCJDT04iLCJDU1QiLCJDT1UiLCJEQ0ciLCJETkwiLCJERU0iLCJEL0MiLCJERkwiLCJER1IiLCJGRUQiLCJGTFAiLCJGUkUiLCJHV1AiLCJHUlQiLCJHUkUiLCJHUiIsIkhSUCIsIklEUCIsIklORCIsIklBUCIsIklDRCIsIklHUiIsIklQIiwiSURFIiwiSUdEIiwiSkNOIiwiSlVTIiwiTFJVIiwiTEJSIiwiTEZUIiwiTEJMIiwiTElCIiwiTEJVIiwiTVRQIiwiTkRQIiwiTkxQIiwiTkEiLCJOSkMiLCJOUFAiLCJOUEEiLCJOT1AiLCJOTkUiLCJOIiwiTk9OIiwiT0UiLCJPVEgiLCJQRyIsIlBTTCIsIlBBRiIsIlBGUCIsIlBGRCIsIlBPUCIsIlBQWSIsIlBDSCIsIlBQRCIsIlBSTyIsIk5BUCIsIlBSSSIsIlJVUCIsIlJFRiIsIlJFUCIsIlJFUyIsIlJUTCIsIlNFUCIsIlNMUCIsIlNVUyIsIlNPQyIsIlNXUCIsIlRYIiwiVFdSIiwiVEVBIiwiVEhEIiwiTEFCIiwiVVNQIiwiVVNUIiwiVU4iLCJVQyIsIlVOSSIsIlVOSyIsIlZFVCIsIldUUCIsIlciKSwNCiAgTGFiZWwgPSBjKCJBY2UgUGFydHkiLCJBbGFza2FuIEluZGVwZW5kZW5jZSBQYXJ0eSIsIkFtZXJpY2FuIEluZGVwZW5kZW50IENvbnNlcnZhdGl2ZSIsIkFtZXJpY2FuIEluZGVwZW5kZW50IFBhcnR5IiwiQW1lcmljYW4gUGFydHkiLCJBbWVyaWNhbiBQZW9wbGUncyBGcmVlZG9tIFBhcnR5IiwiQW1lcmljYW5zIEVsZWN0IiwiQ2l0aXplbnMnIFBhcnR5IiwiQ29tbWFuZG1lbnRzIFBhcnR5IiwiQ29tbW9ud2VhbHRoIFBhcnR5IG9mIHRoZSBVLlMuIiwiQ29tbXVuaXN0IFBhcnR5IiwiQ29uY2VybmVkIENpdGl6ZW5zIFBhcnR5IE9mIENvbm5lY3RpY3V0IiwiQ29uc2VydmF0aXZlIFBhcnR5IiwiQ29uc3RpdHV0aW9uIFBhcnR5IiwiQ29uc3RpdHV0aW9uYWwiLCJDb3VudHJ5IiwiRC5DLiBTdGF0ZWhvb2QgR3JlZW4gUGFydHkiLCJEZW1vY3JhdGljIC1Ob25wYXJ0aXNhbiBMZWFndWUiLCJEZW1vY3JhdGljIFBhcnR5IiwiRGVtb2NyYXRpYy9Db25zZXJ2YXRpdmUiLCJEZW1vY3JhdGljLUZhcm1lci1MYWJvciIsIkRlc2VydCBHcmVlbiBQYXJ0eSIsIkZlZGVyYWxpc3QiLCJGcmVlZG9tIExhYm9yIFBhcnR5IiwiRnJlZWRvbSBQYXJ0eSIsIkdlb3JnZSBXYWxsYWNlIFBhcnR5IiwiR3Jhc3Nyb290cyIsIkdyZWVuIFBhcnR5IiwiR3JlZW4tUmFpbmJvdyIsIkh1bWFuIFJpZ2h0cyBQYXJ0eSIsIkluZGVwZW5kZW5jZSBQYXJ0eSIsIkluZGVwZW5kZW50IiwiSW5kZXBlbmRlbnQgQW1lcmljYW4gUGFydHkiLCJJbmRlcGVuZGVudCBDb25zZXJ2YXRpdmUgRGVtb2NyYXRpYyIsIkluZGVwZW5kZW50IEdyZWVuIiwiSW5kZXBlbmRlbnQgUGFydHkiLCJJbmRlcGVuZGVudCBQYXJ0eSBvZiBEZWxhd2FyZSIsIkluZHVzdHJpYWwgR292ZXJubWVudCBQYXJ0eSIsIkpld2lzaC9DaHJpc3RpYW4gTmF0aW9uYWwiLCJKdXN0aWNlIFBhcnR5IiwiTGEgUmF6YSBVbmlkYSIsIkxhYm9yIFBhcnR5IiwiTGVzcyBGZWRlcmFsIFRheGVzIiwiTGliZXJhbCBQYXJ0eSIsIkxpYmVydGFyaWFuIFBhcnR5IiwiTGliZXJ0eSBVbmlvbiBQYXJ0eSIsIk1vdW50YWluIFBhcnR5IiwiTmF0aW9uYWwgRGVtb2NyYXRpYyBQYXJ0eSIsIk5hdHVyYWwgTGF3IFBhcnR5IiwiTmV3IEFsbGlhbmNlIiwiTmV3IEplcnNleSBDb25zZXJ2YXRpdmUgUGFydHkiLCJOZXcgUHJvZ3Jlc3NpdmUgUGFydHkiLCJObyBQYXJ0eSBBZmZpbGlhdGlvbiIsIk5vIFBhcnR5IFByZWZlcmVuY2UiLCJOb25lIiwiTm9ucGFydGlzYW4iLCJOb24tUGFydHkiLCJPbmUgRWFydGggUGFydHkiLCJPdGhlciIsIlBhY2lmaWMgR3JlZW4iLCJQYXJ0eSBmb3IgU29jaWFsaXNtIGFuZCBMaWJlcmF0aW9uIiwiUGVhY2UgQW5kIEZyZWVkb20iLCJQZWFjZSBBbmQgRnJlZWRvbSBQYXJ0eSIsIlBlYWNlIEZyZWVkb20gUGFydHkiLCJQZW9wbGUgT3ZlciBQb2xpdGljcyIsIlBlb3BsZSdzIFBhcnR5IiwiUGVyc29uYWwgQ2hvaWNlIFBhcnR5IiwiUG9wdWxhciBEZW1vY3JhdGljIFBhcnR5IiwiUHJvZ3Jlc3NpdmUgUGFydHkiLCJQcm9oaWJpdGlvbiBQYXJ0eSIsIlB1ZXJ0byBSaWNhbiBJbmRlcGVuZGVuY2UgUGFydHkiLCJSYXphIFVuaWRhIFBhcnR5IiwiUmVmb3JtIFBhcnR5IiwiUmVwdWJsaWNhbiBQYXJ0eSIsIlJlc291cmNlIFBhcnR5IiwiUmlnaHQgVG8gTGlmZSIsIlNvY2lhbGlzdCBFcXVhbGl0eSBQYXJ0eSIsIlNvY2lhbGlzdCBMYWJvciBQYXJ0eSIsIlNvY2lhbGlzdCBQYXJ0eSIsIlNvY2lhbGlzdCBQYXJ0eSBVLlMuQS4iLCJTb2NpYWxpc3QgV29ya2VycyBQYXJ0eSIsIlRheHBheWVycyIsIlRheHBheWVycyBXaXRob3V0IFJlcHJlc2VudGF0aW9uIiwiVGVhIFBhcnR5IiwiVGhlby1EZW1vY3JhdGljIiwiVS5TLiBMYWJvciBQYXJ0eSIsIlUuUy4gUGVvcGxlJ3MgUGFydHkiLCJVLlMuIFRheHBheWVycyBQYXJ0eSIsIlVuYWZmaWxpYXRlZCIsIlVuaXRlZCBDaXRpemVuIiwiVW5pdGVkIFBhcnR5IiwiVW5rbm93biIsIlZldGVyYW5zIFBhcnR5IiwiV2UgdGhlIFBlb3BsZSIsIldyaXRlLUluIikNCikNCg0KDQoNCmBgYA0KDQpgYGB7cn0NCmNhbmRfZGF0YSA8LSAgcmVhZC5jc3YyKGZpbGUgPSAiQzovVXNlcnMvMTgxMzcvRG93bmxvYWRzL2NhbmRpZGF0ZV9zdW1tYXJ5XzIwMjAuY3N2Iiwgc2VwID0gIiwiICwgKQ0KY2FuZF9kYXRhJFRvdGFsX0NvbnRyaWJ1dGlvbiA8LSBhcy5udW1lcmljKGNhbmRfZGF0YSRUb3RhbF9Db250cmlidXRpb24pDQpjYW5kX2RhdGEkVG90YWxfUmVjZWlwdCA8LSBhcy5udW1lcmljKGNhbmRfZGF0YSRUb3RhbF9SZWNlaXB0KQ0KDQpjYW5kX2RhdGEgPC0gY2FuZF9kYXRhICU+JQ0KICBsZWZ0X2pvaW4ocGFydHlfZGljdGlvbmFyeSwgYnkgPSBjKCJDYW5kX1BhcnR5X0FmZmlsaWF0aW9uIiA9ICJPcmlnaW5hbCIpKSAlPiUNCiAgIyBPcHRpb25hbGx5LCB5b3UgbWlnaHQgd2FudCB0byByZW1vdmUgdGhlIG9yaWdpbmFsIGNvbHVtbiBhbmQgcmVuYW1lIHRoZSBuZXcgb25lDQogIHNlbGVjdCgtQ2FuZF9QYXJ0eV9BZmZpbGlhdGlvbikgJT4lDQogIHJlbmFtZShDYW5kX1BhcnR5X0FmZmlsaWF0aW9uID0gTGFiZWwpDQoNCmVsZWN0aW9uX3Jlc3VsdHMgPC0gcmVhZF9leGNlbCgiQzovVXNlcnMvMTgxMzcvRG93bmxvYWRzL2ZlZGVyYWxlbGVjdGlvbnMyMDIwLnhsc3giKQ0KDQpzZW5hdGVfcmVzdWx0cyA8LSByZWFkX2V4Y2VsKCJDOi9Vc2Vycy8xODEzNy9Eb3dubG9hZHMvZmVkZXJhbGVsZWN0aW9uczIwMjAueGxzeCIsIHNoZWV0ID0gIjEyLiBVUyBTZW5hdGUgUmVzdWx0cyBieSBTdGF0ZSIpDQpob3VzZV9yZXN1bHRzIDwtIHJlYWRfZXhjZWwoIkM6L1VzZXJzLzE4MTM3L0Rvd25sb2Fkcy9mZWRlcmFsZWxlY3Rpb25zMjAyMC54bHN4Iiwgc2hlZXQgPSAiMTMuIFVTIEhvdXNlIFJlc3VsdHMgYnkgU3RhdGUiKQ0KcHJlc19wcmltYXJ5X3Jlc3VsdHMgPC0gcmVhZF9leGNlbCgiQzovVXNlcnMvMTgxMzcvRG93bmxvYWRzL2ZlZGVyYWxlbGVjdGlvbnMyMDIwLnhsc3giLCBzaGVldCA9ICI5LiAyMDIwIFByZXMgR2VuZXJhbCBSZXN1bHRzIikNCmBgYA0KDQpgYGB7cn0NCnNlbmF0ZV9yZXN1bHRzIDwtIHNlbmF0ZV9yZXN1bHRzICU+JQ0KICBtdXRhdGUoV2luX0xvc2UgPSBhcy5udW1lcmljKCdHRSBXaW5uZXIgSW5kaWNhdG9yJyA9PSAiVyIpKQ0KDQpob3VzZV9yZXN1bHRzIDwtIGhvdXNlX3Jlc3VsdHMgJT4lDQogIG11dGF0ZShXaW5fTG9zZSA9IGFzLm51bWVyaWMoJ0dFIFdpbm5lciBJbmRpY2F0b3InID09ICJXIikpDQoNCnByZXNfcHJpbWFyeV9yZXN1bHRzIDwtIHByZXNfcHJpbWFyeV9yZXN1bHRzICU+JQ0KICBtdXRhdGUoV2luX0xvc2UgPSBhcy5udW1lcmljKCdXaW5uZXJfSW5kaWNhdG9yJyA9PSAiVyIpKQ0KYGBgDQoNCmBgYHtyfQ0KY2FuZF9kYXRhIDwtIGNhbmRfZGF0YSAlPiUgZ3JvdXBfYnkoQ2FuZF9QYXJ0eV9BZmZpbGlhdGlvbikgJT4lIGZpbHRlcihUb3RhbF9SZWNlaXB0ID4gMCkNCg0KDQphbGxfZWxlY3Rpb25fcmVzdWx0cyA8LSBiaW5kX3Jvd3Moc2VuYXRlX3Jlc3VsdHMsIGhvdXNlX3Jlc3VsdHMsIHByZXNfcHJpbWFyeV9yZXN1bHRzKQ0KDQpmaW5hbF9kYXRhIDwtIGNhbmRfZGF0YSAlPiUNCiAgbGVmdF9qb2luKGFsbF9lbGVjdGlvbl9yZXN1bHRzLCBieSA9IGMoIkNhbmRfSWQiID0gIkZFQyBJRCIpKQ0KDQoNCmZpbmFsX2RhdGEkV2luX0xvc2VbaXMubmEoZmluYWxfZGF0YSRXaW5fTG9zZSldIDwtIDANCmhlYWQoZmluYWxfZGF0YSkNCg0KbWVyZ2VkX2RhdGEgPC0gZmluYWxfZGF0YSAlPiUNCiAgbXV0YXRlKFRvdGFsX0NvbnRyaWJ1dGlvbiA9IGlmX2Vsc2UoaXMubmEoVG90YWxfQ29udHJpYnV0aW9uKSwgbWVkaWFuKFRvdGFsX0NvbnRyaWJ1dGlvbiwgbmEucm0gPSBUUlVFKSwgVG90YWxfQ29udHJpYnV0aW9uKSkNCg0Kc3VtbWFyeShtZXJnZWRfZGF0YSkNCg0KDQpgYGANCg0KYGBge3J9DQojIEVuc3VyZSBXaW5fTG9zZSBpcyBhIGZhY3RvciBmb3IgbG9naXN0aWMgcmVncmVzc2lvbg0KbWVyZ2VkX2RhdGEkV2luX0xvc2UgPC0gYXMuZmFjdG9yKG1lcmdlZF9kYXRhJFdpbl9Mb3NlKQ0KDQojIEZpdCB0aGUgbW9kZWwNCm1vZGVsIDwtIGdsbShXaW5fTG9zZSB+IFRvdGFsX0NvbnRyaWJ1dGlvbiwgZGF0YSA9IG1lcmdlZF9kYXRhLCBmYW1pbHkgPSBiaW5vbWlhbCgpLGNvbnRyb2wgPSBnbG0uY29udHJvbChtYXhpdCA9IDEwMDAwKSkNCg0KIyBDaGVjayB0aGUgc3VtbWFyeQ0Kc3VtbWFyeShtb2RlbCkNCmBgYA0KDQpgYGB7cn0NCnNldC5zZWVkKDEyMykgICMgZm9yIHJlcHJvZHVjaWJpbGl0eQ0KdHJhaW5pbmdfc2FtcGxlcyA8LSBjcmVhdGVEYXRhUGFydGl0aW9uKG1lcmdlZF9kYXRhJFdpbl9Mb3NlLCBwID0gMC44LCBsaXN0ID0gRkFMU0UpDQoNCnRyYWluX2RhdGEgPC0gbWVyZ2VkX2RhdGFbdHJhaW5pbmdfc2FtcGxlcywgXQ0KdGVzdF9kYXRhIDwtIG1lcmdlZF9kYXRhWy10cmFpbmluZ19zYW1wbGVzLCBdDQoNCiMgUHJlZGljdCBvbiB0ZXN0IHNldA0KcHJlZGljdGlvbnMgPC0gcHJlZGljdChtb2RlbCwgdGVzdF9kYXRhLCB0eXBlID0gInJlc3BvbnNlIikNCnByZWRpY3RlZF9jbGFzcyA8LSBpZl9lbHNlKHByZWRpY3Rpb25zID4gMC41LCAxLCAwKQ0KDQojIEFkanVzdGluZyB0aGUgc2FtcGxpbmcgbWV0aG9kIHRvIGVuc3VyZSBzdHJhdGlmaWNhdGlvbg0KdHJhaW5pbmdfc2FtcGxlcyA8LSBjcmVhdGVEYXRhUGFydGl0aW9uKG1lcmdlZF9kYXRhJFdpbl9Mb3NlLCBwID0gMC44LCBsaXN0ID0gVFJVRSwgdGltZXMgPSAxKQ0KDQp0cmFpbl9kYXRhIDwtIG1lcmdlZF9kYXRhW3RyYWluaW5nX3NhbXBsZXNbWzFdXSwgXQ0KdGVzdF9kYXRhIDwtIG1lcmdlZF9kYXRhWy10cmFpbmluZ19zYW1wbGVzW1sxXV0sIF0NCg0KdGVzdF9kYXRhJFdpbl9Mb3NlIDwtIGZhY3Rvcih0ZXN0X2RhdGEkV2luX0xvc2UsIGxldmVscyA9IGMoIjAiLCAiMSIpKQ0KDQojIEVuc3VyZSBwcmVkaWN0ZWRfY2xhc3MgaXMgYSBmYWN0b3Igd2l0aCBib3RoIGxldmVscw0KcHJlZGljdGVkX2NsYXNzIDwtIGZhY3RvcihwcmVkaWN0ZWRfY2xhc3MsIGxldmVscyA9IGMoIjAiLCAiMSIpKQ0KDQpjb25mdXNpb25NYXRyaXgocHJlZGljdGVkX2NsYXNzLCB0ZXN0X2RhdGEkV2luX0xvc2UpDQoNCiMgQ2FsY3VsYXRlIGFjY3VyYWN5IG9yIG90aGVyIHBlcmZvcm1hbmNlIG1ldHJpY3MNCmFjY3VyYWN5IDwtIHN1bShwcmVkaWN0ZWRfY2xhc3MgPT0gdGVzdF9kYXRhJFdpbl9Mb3NlKSAvIG5yb3codGVzdF9kYXRhKQ0KcHJpbnQocGFzdGUoIkFjY3VyYWN5OiIsIGFjY3VyYWN5KSkNCg0KYGBgDQoNCg0KYGBge3J9DQpjb25Ub3RhbCA8LSBjYW5kX2RhdGEkVG90YWxfQ29udHJpYnV0aW9uIA0KDQpmaWcxIDwtIGNhbmRfZGF0YSAlPiUgDQogIGdncGxvdChhZXMoY29uVG90YWwsIENhbmRfU3RhdGUpKSArIGdlb21fY29sKGFlcyhmaWxsID0gY2FuZF9kYXRhJENhbmRfU3RhdGUpKSArIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX2RvbGxhcihwcmVmaXggPSAiJCIpKQ0KDQpnZ3Bsb3RseShmaWcxKQ0KYGBgDQpgYGB7cn0NCmNhbmRfYnlfYWZmaWxpYXRpb25fVG90YWxfUmVjZWlwdCA8LSBjYW5kX2RhdGEgJT4lIA0KICBncm91cF9ieShDYW5kX1BhcnR5X0FmZmlsaWF0aW9uKSAlPiUgDQogIGZpbHRlcihUb3RhbF9SZWNlaXB0ID4gMCkgJT4lIA0KICBhcnJhbmdlKFRvdGFsX1JlY2VpcHQpDQoNCg0KY2FuZF9ieV9hZmZpbGlhdGlvbl9Ub3RhbF9SZWNlaXB0IDwtIGRhdGEuZnJhbWUoY2FuZF9ieV9hZmZpbGlhdGlvbl9Ub3RhbF9SZWNlaXB0JENhbmRfUGFydHlfQWZmaWxpYXRpb24sIGNhbmRfYnlfYWZmaWxpYXRpb25fVG90YWxfUmVjZWlwdCRUb3RhbF9SZWNlaXB0KQ0KDQphcmdfZGF0YSA8LSBhZ2dyZWdhdGUoY2FuZF9ieV9hZmZpbGlhdGlvbl9Ub3RhbF9SZWNlaXB0JGNhbmRfYnlfYWZmaWxpYXRpb25fVG90YWxfUmVjZWlwdC5Ub3RhbF9SZWNlaXB0LA0KICBsaXN0KENhdGVnb3J5ID0gY2FuZF9ieV9hZmZpbGlhdGlvbl9Ub3RhbF9SZWNlaXB0JGNhbmRfYnlfYWZmaWxpYXRpb25fVG90YWxfUmVjZWlwdC5DYW5kX1BhcnR5X0FmZmlsaWF0aW9uKSwNCiAgc3VtKQ0KDQphcmdfZGF0YSA8LSBhcmdfZGF0YSAlPiUgdG9wX24oMikNCg0KZ2dwbG90KGFyZ19kYXRhLCBhZXMoeCA9IENhdGVnb3J5LCB5ID0geCkpICsgIGdlb21fY29sKGFlcyhmaWxsID0gQ2F0ZWdvcnkpKSArIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX2RvbGxhcihwcmVmaXggPSAiJCIsIHN1ZmZpeCA9ICIiKSkNCmBgYA0KDQoNCmBgYHtyfQ0KIyBBc3N1bWluZyAnY2FuZF9kYXRhJyBpcyB5b3VyIGRhdGEgZnJhbWUgYW5kIGl0IGhhcyBiZWVuIGxvYWRlZCBpbnRvIHlvdXIgUiBzZXNzaW9uDQpkaXN0aW5jdF9wYXJ0aWVzIDwtIGNhbmRfZGF0YSAlPiUNCiAgc2VsZWN0KENhbmRfUGFydHlfQWZmaWxpYXRpb24pICU+JSAgIyBTZWxlY3QgdGhlIGNvbHVtbiBvZiBpbnRlcmVzdA0KICBkaXN0aW5jdCgpICU+JSAgICAgICAgICAgICAgICAgICAgICAjIEdldCBkaXN0aW5jdC91bmlxdWUgZW50cmllcw0KICBhcnJhbmdlKENhbmRfUGFydHlfQWZmaWxpYXRpb24pICAgICAjIE9wdGlvbmFsOiBhcnJhbmdlIHRoZW0gYWxwaGFiZXRpY2FsbHkNCg0KIyBUbyB2aWV3IHRoZSBkaXN0aW5jdCBwYXJ0eSBhZmZpbGlhdGlvbnMNCnByaW50KGRpc3RpbmN0X3BhcnRpZXMpDQpgYGANCg0KDQpgYGB7cn0NCnJlY2VpcHRfZGF0YSA8LSBjYW5kX2RhdGEgJT4lDQogICAgZ3JvdXBfYnkoQ2FuZF9QYXJ0eV9BZmZpbGlhdGlvbikgJT4lDQogICAgc3VtbWFyaXplKFRvdGFsX1JlY2VpcHQgPSBzdW0oVG90YWxfUmVjZWlwdCwgbmEucm0gPSBUUlVFKSkgJT4lDQogICAgZmlsdGVyKFRvdGFsX1JlY2VpcHQgPiAwKSAlPiUgIA0KICAgIGdncGxvdChhZXMoeCA9IENhbmRfUGFydHlfQWZmaWxpYXRpb24sIHkgPSBUb3RhbF9SZWNlaXB0LCBmaWxsID0gQ2FuZF9QYXJ0eV9BZmZpbGlhdGlvbikpICsNCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICAgIHNjYWxlX2ZpbGxfdmlyaWRpcyhkaXNjcmV0ZSA9IFRSVUUsIG9wdGlvbiA9ICJNIikgKw0KICAgIHNjYWxlX3lfbG9nMTAobGFiZWxzID0gbGFiZWxfZG9sbGFyKHNjYWxlID0gMSkpICsNCiAgICBsYWJzKHggPSAiUGFydHkgQWZmaWxpYXRpb24iLA0KICAgICAgICAgeSA9ICJMb2cgb2YgVG90YWwgUmVjZWlwdHMgKERvbGxhcnMpIiwNCiAgICAgICAgIHRpdGxlID0gIlRvdGFsIFJlY2VpcHRzIGJ5IFBhcnR5IEFmZmlsaWF0aW9uIikgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxLCB2anVzdCA9IDAuNSkpDQoNCnBsb3RseV9yZWNlaXB0X2RhdGEgPC0gZ2dwbG90bHkocmVjZWlwdF9kYXRhKQ0KcGxvdGx5X3JlY2VpcHRfZGF0YQ0KYGBgDQoNCmBgYHtyfQ0KQ29uZ3Jlc3Npb25hbF9kYXRhIDwtIGNhbmRfZGF0YSAlPiUgDQogIGdyb3VwX2J5KENhbmRfT2ZmaWNlKSAlPiUgDQogIGZpbHRlcihDYW5kX09mZmljZSAhPSAiUCIpICU+JSANCiAgYXJyYW5nZShUb3RhbF9Db250cmlidXRpb24pDQoNCkNvbmdyZXNzaW9uYWxfZGF0YSA8LSBhZ2dyZWdhdGUoQ29uZ3Jlc3Npb25hbF9kYXRhJFRvdGFsX0NvbnRyaWJ1dGlvbiwNCiAgbGlzdChDYXRlZ29yeSA9IENvbmdyZXNzaW9uYWxfZGF0YSRDYW5kX09mZmljZSApLA0KICBzdW0pDQoNCnByZXNpZGVudF9kYXRhIDwtIGNhbmRfZGF0YSAlPiUgDQogIGdyb3VwX2J5KENhbmRfT2ZmaWNlKSAlPiUgDQogIGZpbHRlcihDYW5kX09mZmljZSA9PSAiUCIpICU+JSANCiAgYXJyYW5nZShUb3RhbF9Db250cmlidXRpb24pDQpgYGANCg0KDQpgYGB7cn0NCkNvbmdyZXNzaW9uYWxfZGF0YSAlPiUgZ2dwbG90KGFlcyh4ID0geCwgeSA9IENhdGVnb3J5KSkgKyBnZW9tX2NvbChhZXMoZmlsbCA9IENhdGVnb3J5KSkgKyBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWwgPSBzY2FsZXM6OmxhYmVsX2RvbGxhcihwcmVmaXggPSAiJCIpKQ0KYGBgDQoNCg0KYGBge3J9DQpmaWcxIDwtIGNhbmRfZGF0YSAlPiUNCiAgICBncm91cF9ieShDYW5kX1N0YXRlKSAlPiUNCiAgICBzdW1tYXJpc2UoVG90YWxfQ29udHJpYnV0aW9uID0gc3VtKFRvdGFsX0NvbnRyaWJ1dGlvbikpICU+JQ0KICAgIGZpbHRlcihUb3RhbF9Db250cmlidXRpb24gPiAwKSAlPiUgICMgRmlsdGVyaW5nIG91dCB6ZXJvcw0KICAgIGdncGxvdChhZXMoeCA9IENhbmRfU3RhdGUsIHkgPSBUb3RhbF9Db250cmlidXRpb24sIGZpbGwgPSBDYW5kX1N0YXRlKSkgKw0KICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArDQogICAgc2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVFJVRSwgb3B0aW9uID0gIkQiKSArICAjIFVzaW5nIHZpcmlkaXMgZm9yIGRpc2NyZXRlIGNvbG9yIG1hcHBpbmcNCiAgICBzY2FsZV95X2xvZzEwKGxhYmVscyA9IHNjYWxlczo6bGFiZWxfZG9sbGFyKHNjYWxlID0gMSkpICsgICMgRm9ybWF0dGluZyB5LWF4aXMgYXMgZG9sbGFyIHZhbHVlcw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgbGFicyh0aXRsZSA9ICJUb3RhbCBDb250cmlidXRpb25zIGJ5IFN0YXRlIiwNCiAgICAgICAgIHkgPSAiTG9nIG9mIFRvdGFsIENvbnRyaWJ1dGlvbnMgKERvbGxhcnMpIiwNCiAgICAgICAgIHggPSAiU3RhdGUiKSArDQogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxLCB2anVzdCA9IDAuNSkpICAjIFZlcnRpY2FsIHgtYXhpcyBsYWJlbHMNCg0KIyBDb252ZXJ0IHRvIFBsb3RseSBpbnRlcmFjdGl2ZSBwbG90DQpwbG90bHlfZmlnMSA8LSBnZ3Bsb3RseShmaWcxKQ0KcGxvdGx5X2ZpZzENCg0KYGBgDQoNCg0K